package personal.zq.practice.common.utils;

import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
import java.util.TimeZone;
import org.apache.commons.lang3.time.DateFormatUtils;
import personal.zq.practice.common.constants.Constants;

/**
 * @version V1.0
 * @PackageName: com.zhilingsd.cpic.marketing.business.common.utils
 * @ClassName: TimeUtils
 * @Description:
 * @Author roxulo
 * @Date 2021/2/19
 */
public class TimeUtils {

    /**
     * 默认时间
     */
    public static final String DEFAULT_TIME = "00:00:00";

    /**
     * replace by
     *
     * @param time
     * @return
     * @see #convertTimeDesc(Date)
     */
    @Deprecated
    public static String getTimeDesc(Date time) {
        long[] todayAndYesterdayTimestamp = getTodayAndYesterdayTimestamp();
        long timestamp = time.getTime();
        long todayBeginTime = todayAndYesterdayTimestamp[0];
        if (timestamp >= todayBeginTime) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm");
            String prefix = time.getTime() > todayBeginTime + (12 * 60 * 60 * 1000) ? "下午" : "上午";
            return prefix + dateFormat.format(time);
        } else if (timestamp >= todayAndYesterdayTimestamp[1]) {
            return "昨天";
        } else {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
            return dateFormat.format(time);
        }
    }

    /**
     * ①一天内12点前显示上午+时间(如上午9:37)；
     * ②一天内12点后显示下午+时间(如下午4:30)；
     * ③超过一天（超过凌晨12点算新的一天）小于2天，显示昨天(如昨天)；
     * ④超过2天，显示月日(如9月23日);
     * ⑤超过1年显示yyyy年mm月dd日（如2020年09月30日）
     *
     * @param time
     * @return
     */
    public static String convertTimeDesc(Date time) {
        return convertTimeDescWithFormat(time, "yyyy年M月d日", "M月d日");
    }

    public static String convertTimeDescWithFormat(Date time, String yMdFormat, String mdFormat) {
        LocalDateTime paramDate = time.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        // before year
        LocalDate yearStart = LocalDate.of(LocalDate.now().getYear(), 1, 1);
        Duration duration = Duration.between(paramDate, yearStart.atStartOfDay());
        if (duration.toMillis() > 0) {
            return DateFormatUtils.format(time, yMdFormat);
        }
        // year
        duration = Duration.between(paramDate, LocalDate.now().atStartOfDay());
        // before yesterday
        if (duration.toMillis() >= 24 * 60 * 60 * 1000) {
            return DateFormatUtils.format(time, mdFormat);
        }
        // yesterday
        if (duration.toMillis() > 0) {
            return "昨天";
        }
        // today
        String prefix = duration.toMillis() > -12 * 60 * 60 * 1000 ? "上午" : "下午";
        String timeStr = DateFormatUtils.format(time, "h:mm");
        return prefix + timeStr;
    }

    public static long[] getTodayAndYesterdayTimestamp() {
        long[] timestamp = new long[2];
        Calendar today = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
        today.set(Calendar.HOUR_OF_DAY, 0);
        today.set(Calendar.MINUTE, 0);
        today.set(Calendar.SECOND, 0);
        today.set(Calendar.MILLISECOND, 0);
        timestamp[0] = today.getTime().getTime();

        Calendar yesterday = today;
        yesterday.add(Calendar.HOUR, -24);
        timestamp[1] = yesterday.getTime().getTime();
        return timestamp;
    }


    /**
     * 获取当天开始时刻 ： yyyy-MM-dd HH:mm:ss
     * eg. 2020-02-01 00:00:00
     *
     * @param date localDate
     * @return
     */
    public static Date getStartOfDay(LocalDate date) {
        return localDate2Date(date.atStartOfDay());
    }

    /**
     * 获取当天结尾时刻 ： yyyy-MM-dd HH:mm:ss
     * eg. 2020-02-01 23:59:59.999999999
     *
     * @param date localDate
     * @return
     */
    public static Date getEndOfDay(LocalDate date) {
        return localDate2Date(LocalDateTime.of(date, LocalTime.MAX));
    }

    /**
     * localDateTime 转 Date
     *
     * @param dateTime LocalDateTime
     * @return
     */
    public static Date localDate2Date(LocalDateTime dateTime) {
        return Date.from(dateTime.toInstant(ZoneOffset.of(Constants.SYSTEM_TIME_OFFSET_ID)));
    }

    /**
     * 秒转换成时间格式
     *
     * @param totalTime
     * @return
     */
    public static String totalTime(Integer totalTime) {
        if (totalTime == null) {
            return Constants.DEFAULT_TIME;
        }
        int min = Math.round((totalTime % 3600) / 60);
        int second = totalTime % 60;
        int hour = totalTime / 3600;
        return formatTime(hour) + ":" + formatTime(min) + ":" + formatTime(second);
    }

    private static String formatTime(int time) {
        if (time < 10) {
            return "0" + time;
        } else {
            return "" + time;
        }
    }


    public static String totalTimeMS(Integer totalTime) {
        if (totalTime == null) {
            return Constants.DEFAULT_TIME_MINUTE;
        }
        int second = totalTime % 60;
        int min = totalTime / 60;
        return formatTime(min) + ":" + formatTime(second);
    }

    /**
     * 判断两个时间是否同一个月
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean inCurrentMonth(Date date1, Date date2) {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(date1);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(date2);
        return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR) && calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
    }

    /**
     * 月周期区间的开始和结束
     *
     * @param years e.g. 2022 年份
     * @param month 1 ~ 12 月份
     * @return
     */
    public static Date[] monthInterval(int years, int month) {
        LocalDate firstDayOfMonth = LocalDate.of(years, month, 1);
        LocalDate lastDayOfMonth = firstDayOfMonth.with(TemporalAdjusters.lastDayOfMonth());
        Date[] monthInterval = new Date[2];
        monthInterval[0] = getStartOfDay(firstDayOfMonth);
        monthInterval[1] = getEndOfDay(lastDayOfMonth);
        return monthInterval;

    }

    /**
     * 季度周期区间的开始和结束
     *
     * @param years   e.g. 2022 年份
     * @param quarter 1 ~ 4 季度
     * @return
     */
    public static Date[] quarterInterval(int years, int quarter) {
        if (quarter > 4 || quarter < 1) {
            throw new IllegalArgumentException("季度参数值不符合要求");
        }
        LocalDate firstDayOfQuarter = LocalDate.of(years, (quarter - 1) * 3 + 1, 1);
        LocalDate lastDayOfQuarter = LocalDate.of(years, quarter * 3, 1).with(TemporalAdjusters.lastDayOfMonth());
        Date[] quarterInterval = new Date[2];
        quarterInterval[0] = getStartOfDay(firstDayOfQuarter);
        quarterInterval[1] = getEndOfDay(lastDayOfQuarter);
        return quarterInterval;
    }

    /**
     * 年周期区间的开始和结束
     *
     * @param years e.g. 2022 年份
     * @return
     */
    public static Date[] yearInterval(int years) {
        LocalDate firstDayOfYear = LocalDate.of(years, 1, 1);
        LocalDate lastDayOfYear = firstDayOfYear.with(TemporalAdjusters.lastDayOfYear());
        Date[] yearInterval = new Date[2];
        yearInterval[0] = getStartOfDay(firstDayOfYear);
        yearInterval[1] = getEndOfDay(lastDayOfYear);
        return yearInterval;
    }

    public static LocalDate toLocalDate(Date date) {
        return LocalDate.from(date.toInstant().atZone(ZoneId.systemDefault()));
    }

    public static LocalDateTime toLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 获取当月开始时间
     *
     * @param date 日期
     * @return 当月开始时间 yyyy-MM-01 00:00:00
     */
    public static Date getStartOfMonth(Date date) {
        LocalDate startLocalDate = LocalDate.parse(DateUtil.getDate(DateUtil.getMonthStart(date), DateUtil.DATE), DateTimeFormatter.ISO_LOCAL_DATE);
        return getStartOfDay(startLocalDate);
    }

    /**
     * 月初
     *
     * @param localDate
     * @return
     */
    public static Date getStartOfMonth(LocalDate localDate) {
        Objects.requireNonNull(localDate);
        return getStartOfDay(localDate.with(TemporalAdjusters.firstDayOfMonth()));
    }

    /**
     * 获取当月结束时间
     *
     * @param date 日期
     * @return 当月结束时间 yyyy-MM-dd 23:59:59
     */
    public static Date getEndOfMonth(Date date) {
        LocalDate endLocalDate = LocalDate.parse(DateUtil.getDate(DateUtil.getMonthEnd(date), DateUtil.DATE), DateTimeFormatter.ISO_LOCAL_DATE);
        return getEndOfDay(endLocalDate);
    }

    /**
     * 月末
     *
     * @param localDate
     * @return
     */
    public static Date getEndOfMonth(LocalDate localDate) {
        Objects.requireNonNull(localDate);
        return TimeUtils.getEndOfDay(localDate.with(TemporalAdjusters.lastDayOfMonth()));
    }
}
